package com.yociyy.config;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.Arrays;

/**
 * oauth认证服务器配置
 * 
 * @author: YoCiyy
 * @date: 2020/6/22
 */
@Configuration
@RequiredArgsConstructor
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

	/** 令牌持久化配置 */
	private final TokenStore tokenStore;
	/** 客户端详情服务 */
	private final ClientDetailsService clientDetailsService;
	/** 用户详情服务 */
	private final UserDetailsService userDetailsService;
	/** 认证管理器 */
	private final AuthenticationManager authenticationManager;
	/** 授权码服务 */
	private final AuthorizationCodeServices authorizationCodeServices;
	/** jwtToken解析器 */
	@Autowired(required = false)
	private JwtAccessTokenConverter jwtAccessTokenConverter;
	/** token增强器 */
	@Autowired(required = false)
	private TokenEnhancer tokenEnhancer;

	/**
	 * 客户端详情服务配置 （demo采用本地内存存储）
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		clients
				// 使用本地内存存储
				.inMemory()
				// 客户端id
				.withClient("client_1")
				// 客户端密码
				.secret(new BCryptPasswordEncoder().encode("123456"))
				// 该客户端允许授权的类型
				.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
				// 该客户端允许授权的范围
				.scopes("all")
				// false跳转到授权页面，true不跳转，直接发令牌
				.autoApprove(false);
	}

	/**
	 * 配置访问令牌端点
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
		endpoints
				// 令牌管理
				.tokenStore(tokenStore)
				// 认证管理器
				.authenticationManager(authenticationManager)
				// 授权码服务
				.authorizationCodeServices(authorizationCodeServices)
				// 用户详情服务 refresh_token需要userDetailsService
				.reuseRefreshTokens(false)
				.userDetailsService(userDetailsService)
				// 允许token端点的请求方式
				.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);

		// 令牌管理服务 yoci.security.oauth2.tokenStore.type=rsa-jwt-server 那么使用的是JWT
		if (jwtAccessTokenConverter != null && tokenEnhancer != null) {
			TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
			tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer, jwtAccessTokenConverter));
			endpoints.tokenEnhancer(tokenEnhancerChain);
		}
	}

	/**
	 * 配置令牌端点安全约束
	 */
	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) {
		security
				// oauth/check_token公开
				.checkTokenAccess("permitAll()")
				// oauth/token_key 公开密钥
				.tokenKeyAccess("permitAll()")
				// 允许表单认证
				.allowFormAuthenticationForClients();
	}

	/**
	 * 令牌服务配置
	 * 
	 * @return 令牌服务对象
	 */
	// public AuthorizationServerTokenServices tokenServices() {
	// DefaultTokenServices tokenServices = new DefaultTokenServices();
	// tokenServices.setTokenStore(tokenStore);
	// tokenServices.setSupportRefreshToken(true);
	// // 令牌增强
	// TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
	// tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer, jwtAccessTokenConverter));
	// tokenServices.setTokenEnhancer(tokenEnhancerChain);
	// // 令牌默认有效期2小时
	// tokenServices.setAccessTokenValiditySeconds(7200);
	// // 刷新令牌默认有效期3天
	// tokenServices.setRefreshTokenValiditySeconds(259200);
	// return tokenServices;
	// }

}
